package com.njy.config;

import com.njy.decorator.AsyncDecorator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

import javax.annotation.Resource;
import java.util.concurrent.*;

/**
 * 解决多线程中mdc丢失的重点是将asyncDecorator装饰器放入execute方法中
 * 将asyncDecorator装饰器放入@Async注解
 */
@Configuration
public class AsyncConfig extends AsyncConfigurerSupport {
    @Resource
    private AsyncDecorator asyncDecorator;

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setTaskDecorator(asyncDecorator);
        executor.initialize();
        return executor;
    }

    /**
     * ThreadPoolTaskExecutor注册进入bean交由bean管理
     * @return
     */
    @Bean("threadPoolTaskExecutor")
    public ThreadPoolTaskExecutor threadPoolTaskExecutor(){
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setTaskDecorator(asyncDecorator);
        executor.initialize();
        return executor;
    }

    /**
     * 实现思路为重写ThreadPoolTaskScheduler中方法
     * 将自定义的方法注册到bean中
     * @return
     */
    @Bean("threadPoolTaskScheduler")
    public ThreadPoolTaskScheduler threadPoolTaskScheduler(){
        ThreadPoolTaskScheduler executor = new MdcThreadPoolTaskScheduler();
        return executor;
    }

    /**
     *
     * @return
     */
    @Bean("threadPoolExecutor")
    public ThreadPoolExecutor threadPoolExecutor(){
        int corePoolSize = 10;
        int maximumPoolSize =10;
        long keepAliveTime = 0;
        TimeUnit unit = TimeUnit.MILLISECONDS;
        BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>();
        RejectedExecutionHandler handler  = new ThreadPoolExecutor.DiscardOldestPolicy();
        MdcThreadPoolExecutor executor = new MdcThreadPoolExecutor(corePoolSize,maximumPoolSize,
                keepAliveTime,unit,workQueue,handler);
        return executor;
    }

}
